package org.ktm.exception;

import java.util.Locale;
import org.ktm.utils.KTMResources;
import org.ktm.utils.ParameterizedError;

public class KTMException extends Exception implements ParameterizedError {

    private static final long serialVersionUID = 1L;

    /**
     * The parameters for the error message.
     */
    private Object[]          args             = new Object[0];
    /**
     * The key in the error resource file.
     */
    private String            key;

    /**
     * Construct the KTMException
     */
    public KTMException() {
        this(new KTMResources().getString("ERR_Unspecified", KTMException.class));
    }

    /**
     * Construct the KTMException
     * 
     * @param key
     *            The key in the error resource file pre condition: the key for
     *            an KTMException must always start with ERR_
     */
    public KTMException(String key) {
        if (!key.startsWith("ERR_")) { throw new RuntimeException("ERROR: KTMException: The used key does not start with ERR_, it starts with " + key + " (Class: " + this.toString() + ")"); }
        this.key = key;
    }

    /**
     * Construct the KTMException
     * 
     * @param key
     *            The key in the error resource file
     * @param arg
     *            a single string parameter for the error message
     */
    public KTMException(String key, String arg) {
        this(key, new String[] {
            arg
        });
    }

    /**
     * Construct the KTMException
     * 
     * @param key
     *            The key in the error resource file
     * @param arg1
     *            a string parameter for the error message
     * @param arg2
     *            another string parameter for the error message
     */
    public KTMException(String key, String arg1, String arg2) {
        this(key, new String[] {
        arg1, arg2
        });
    }

    /**
     * Construct the KTMException
     * 
     * @param key
     *            The key in the error resource file
     * @param args
     *            array of parameters for the error message
     */
    public KTMException(String key, Object[] args) {
        this(key);
        this.args = args;
    }

    /**
     * Construct the KTMException
     * 
     * @param cause
     *            the cause (which is saved for later retrieval by the
     *            {@link #getCause()} method). (A <tt>null</tt> value is
     *            permitted, and indicates that the cause is nonexistent or
     *            unknown.)
     */
    public KTMException(Throwable cause) {
        this(new KTMResources().getString("ERR_Unspecified", KTMException.class), cause);
    }

    /**
     * Construct the KTMException
     * 
     * @param key
     *            The key in the error resource file
     * @param cause
     *            the cause (which is saved for later retrieval by the
     *            {@link #getCause()} method). (A <tt>null</tt> value is
     *            permitted, and indicates that the cause is nonexistent or
     *            unknown.)
     */
    public KTMException(String key, Throwable cause) {
        super(cause);
        this.key = key;
    }

    /**
     * Construct the KTMException
     * 
     * @param key
     *            The key in the error resource file
     * @param arg
     *            a single string parameter for the error message
     * @param cause
     *            the cause (which is saved for later retrieval by the
     *            {@link #getCause()} method). (A <tt>null</tt> value is
     *            permitted, and indicates that the cause is nonexistent or
     *            unknown.)
     */
    public KTMException(String key, String arg, Throwable cause) {
        this(key, new String[] {
            arg
        }, cause);
    }

    /**
     * Construct the KTMException
     * 
     * @param key
     *            The key in the error resource file
     * @param arg1
     *            a string parameter for the error message
     * @param arg2
     *            another string parameter for the error message
     * @param cause
     *            the cause (which is saved for later retrieval by the
     *            {@link #getCause()} method). (A <tt>null</tt> value is
     *            permitted, and indicates that the cause is nonexistent or
     *            unknown.)
     */
    public KTMException(String key, String arg1, String arg2, Throwable cause) {
        this(key, new String[] {
        arg1, arg2
        }, cause);
    }

    /**
     * Construct the KTMException
     * 
     * @param key
     *            The key in the error resource file
     * @param args
     *            array of parameters for the error message
     * @param cause
     *            the cause (which is saved for later retrieval by the
     *            {@link #getCause()} method). (A <tt>null</tt> value is
     *            permitted, and indicates that the cause is nonexistent or
     *            unknown.)
     */
    public KTMException(String key, Object[] args, Throwable cause) {
        this(key, cause);
        this.args = args;
    }

    /**
     * Returns this object's key.
     */
    public String getKey() {
        return key;
    }

    /**
     * Returns this object's arguments.
     */
    public Object[] getValues() {
        return args;
    }

    /**
     * Returns a String representation of this object's arguments. The method is
     * required to allow KTMExceptions to be serialized according to the JAX-RPC
     * serialization rules.
     */
    public String[] getStringValues() {
        return getValues() == null || getValues().getClass() != String[].class ? null : (String[]) getValues();
    }

    public void setStringValues(String values[]) {
        args = values;
    }

    /**
     * Return the exception's descriptive message, according to the system
     * locale. The message is obtained from the resource bundle named
     * KgResources{_locale}.properties, which must reside in this exception's
     * package
     */
    @Override
    public String getMessage() {
        return getMessage(KTMException.class);
    }

    public String getMessage(Class<?> clazz) {
        String result = null;
        try {
            result = new KTMResources().getString(getKey(), clazz);
        } catch (Exception ex) {
            result = ex.toString() + ": " + getKey();
        }
        return result;
    }

    /**
     * Return the exception's descriptive message, according to the specified
     * locale. The message is obtained from the resource bundle named
     * KgResources{_locale}.properties, which must reside in this exception's
     * package
     */
    public String getMessage(Locale locale) {
        String result = null;
        try {
            result = new KTMResources().getString(getKey(), (Exception) this, locale);
        } catch (Exception ex) {
            result = ex.toString() + ": " + getKey();
        }
        return result;
    }

    /**
     * Return the exception's descriptive message from a particular resource
     * bundle, using the default (system) locale. The resource bundle is
     * looked-up via the caller's classloader.
     */
    public String getMessage(String qualifiedBundleName, Class<?> clazz) {
        return this.getLocalizedMessage(Locale.getDefault(), qualifiedBundleName, clazz);
    }

    /**
     * Return the exception's descriptive message from a particular resource
     * bundle, using a particular locale. The resource bundle is looked-up via
     * the caller's classloader.
     */
    public String getLocalizedMessage(Locale locale, String bundleName, Class<?> clazz) {
        String result = null;
        String key = super.getMessage();
        try {
            result = new KTMResources().getString(key, locale, bundleName, clazz);

        } catch (Exception exception) {
            result = exception.toString() + ": " + key;
        }
        return result;
    }
}
